/**
 * elSelect JQuery plugin
 * Replacement for select input
 * Allow to put any html and css decoration in drop-down list
 *
 * Usage:
 *   $(selector).elSelect(opts)
 *
 * set value after init:
 *   var c = $(selector).elSelect(opts)
 *   c.val('some value')
 *
 * Get selected value:
 *   var val = c.val();
 *
 * Notice!
 *   1. When called on multiply elements, elSelect create drop-down list only for fist element
 *   2. Elements list created only after first click on element (lazzy loading)
 *
 * Options:
 *   src       - object with pairs value:label to create drop-down list
 *   value     - current (selected) value
 *   class     - css class for display "button" (element on wich plugin was called)
 *   listClass - css class for drop down elements list
 *   select    - callback, called when value was selected (by default write value to console.log)
 *   name      - hidden text field in wich selected value will saved
 *   maxHeight - elements list max height (if height greater - scroll will appear)
 *   tpl       - template for element in list (contains 2 vars: %var - for src key, %label - for src[val])
 *   labelTpl  - template for label (current selected element) (contains 2 placeholders: %var - for src key, %label - for src[val])
 *
 * @author:    Dmitry Levashov (dio) dio@std42.ru
 **/

;(function($){

  $.widget("el.elSelect", {
    options: {
      "name"     : "el-select",
      "class"    : "el-select",
      "listClass": "list",
      "labelTpl" : null,
      "tpl"      : "<%val>%label</%val>",
      "tpls"     : {},
      "value"    : null,
      "src"      : {},
      "select"   : null,
      "maxHeight": 410
    },
    _create     : function()
                  {
                    var self = $.extend(this, {
                      hidden : $("<input />", {type: "hidden", name: this.options.name}),
                      label  : $("<label />", {"class": "rounded-left-3", "unselectable": "on"}),
                      list   : null,
                      ieWidth: 0
                    });
                    if (this.element.is("select"))
                    {
                      $.extend(this.options, {
                        src  : {},
                        value: this.element.val(),
                        name : this.element.attr("name")
                      });
                      var $e = $("<div />");
                      this.element.children("option").each(function(){with($(this))self.options.src[val()]=text();}).end().replaceWith($e);
                      this.element = $e;
                    }
                    if (!(this.options.value && this.options.src[this.options.value]))
                    {
                      this.options.value = null;
                      $.each(this.options.src, function(v){self.options.value=v;return false;});
                    }
                  // init "select"
                    this.element.
                      empty().
                      addClass([this.options["class"], "rounded-3"].join(" ")).
                      attr("unselectable", "on").
                      hover(function(){$(this).addClass("hover");}, function(){$(this).removeClass("hover");}).
                      click(function()
                      {
                        if (!self.list)
                        {
                        // create drop-down list
                        // not ul because of ie is stupid with mouseleave in it :(
                          self.list = $("<div />", {"class": [this.options.listClass, "rounded-3"].join(" "), "style": "display:none;"});
                          $.each(this.options.src, function(v)
                          {
                            $("<div />", {name: v}).
                              append($((self.options.tpls[v] || self.options.tpl).replace(/%val/g, v).replace(/%label/g, this), {unselectable: "on"})).
                              appendTo(self.list);
                          });
                          self.list.children("div").
                            hover(function(){$(this).addClass("hover");}, function(){$(this).removeClass("hover");}).
                            click(function(e)
                            {
                              e.stopPropagation();
                              e.preventDefault();
                              var v = $(this).attr("name");
                              self.val(v);
                              if ($.isFunction(self.options.select))
                                self.options.select(v);
                              self.list.slideUp();
                            }).
                            end().width(Math.max(self.element.outerWidth(), self.list.width()));
                          if (0 < self.options.maxHeight)
                            self.list.height(Math.max(self.options.maxHeight, self.list.height()));
                          self.val(self.hidden.val());
                        }
                        self.list.slideToggle();
                      // stupid ie inherit width from parent
                        if ($.browser.msie && !self.ieWidth)
                        {
                          self.list.children().each(function(){self.ieWidth=Math.max(self.ieWidth,$(this).width());});
                          if (self.list.width() < self.ieWidth)
                            self.list.width(self.ieWidth + 40);
                        }
                      }).
                      mouseleave(function(){self.list.slideUp();});
                    this.hidden.add(this.label).add(this.list).appendTo(this.element);
                    this.val(this.options.value);
                  },
    val         : function(v)
                  {
                    if (v == null)
                     return this.hidden.val();
                    if (this.options.src[v])
                    {
                      this.hidden.val(v);
                      this._updateLabel(v);
                      if (this.list)
                        this.list.children().each(function(){with($(this))toggleClass("active",attr("name")==v);});
                    }
                    return this.element;
                  },
  // update label content
    _updateLabel: function(v)
                  {
                    this.label.
                      html((this.options.labelTpl || this.options.tpls[v] || this.options.tpl || "").replace(/%val/g, v).replace(/%label/, this.options.src[v])).
                      children().attr("unselectable", "on");
                  }
  });

})(jQuery);
